import Watcher from "../observer/watcher";

import { noop } from "../util/index";

export let activeInstance = null;

export function setActiveInstance(vm) {
  const prevActiveInstance = activeInstance;
  activeInstance = vm;
  return () => {
    activeInstance = prevActiveInstance;
  };
}

export function initLifecycle(vm) {
  const options = vm.$options;

  // locate first non-abstract parent
  let parent = options.parent;
  if (parent && !options.abstract) {
    while (parent.$options.abstract && parent.$parent) {
      parent = parent.$parent;
    }
    parent.$children.push(vm);
  }

  vm.$children = [];
}

export function lifecycleMixin(Vue) {
  Vue.prototype._update = function (vnode, hydrating) {
    const vm = this;
    const prevVnode = vm._vnode;
    const restoreActiveInstance = setActiveInstance(vm);
    vm._vnode = vnode;

    if (!prevVnode) {
      vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false);
    }

    restoreActiveInstance();
  };
}

export function mountComponent(vm, el, hydrating) {
  vm.$el = el;
  let updateComponent;
  // _render() 生成vnode
  vm._update(vm._render(), hydrating);
  updateComponent = () => {
    vm._update(vm._render(), hydrating);
    new Watcher(vm, updateComponent, noop, {}, true);
    return vm;
  };
}
